import java.util.HashMap;
import java.util.Map;

public class AISParser4 {


    // 假设 binaryStr 是由之前的 stringTo168bit() 生成的168位二进制字符串
    public static String binaryToUtf8(String binaryStr) throws IllegalArgumentException {
        // 1. 先转换为原始ASCII字符串（使用之前的方法）
        String asciiStr = binaryToOriginalString(binaryStr);

        // 2. 直接作为ASCII字符串使用（UTF-8兼容ASCII）
        return asciiStr;
    }

    public static String binaryToOriginalString(String binaryStr) throws IllegalArgumentException {
        // 检查长度是否为6的倍数
        if (binaryStr.length() % 6 != 0) {
            throw new IllegalArgumentException("Binary string length must be a multiple of 6");
        }

        StringBuilder originalStr = new StringBuilder();

        // 每6位一组进行转换
        for (int i = 0; i < binaryStr.length(); i += 6) {
            String sixBits = binaryStr.substring(i, i + 6);
            char c = sixBitToAscii(sixBits);
            originalStr.append(c);
        }

        return originalStr.toString();
    }

    public static char sixBitToAscii(String sixBitStr) throws IllegalArgumentException {


        int binaryValue = Integer.parseInt(sixBitStr, 2);

        // 逆向计算原始ASCII码
        int temp = binaryValue;
        if (temp > 0x80) {
            temp -= 0x20;
        } else {
            temp -= 0x28;
        }
        temp -= 0x28;

        return (char) temp;
    }

    public static String asciiTo6bit(int asciiCode) throws IllegalArgumentException {
        // Range checks
        if (asciiCode < 0x30 || asciiCode > 0x77) {
            throw new IllegalArgumentException("Data error: ASCII code " + asciiCode + " out of range");
        }
        if (0x58 <= asciiCode && asciiCode <= 0x59) {
            throw new IllegalArgumentException("Data error: ASCII code " + asciiCode + " in reserved range");
        }

        // Numerical calculation
        int temp = asciiCode + 0x28;
        if (temp > 0x80) {
            temp += 0x20;
        } else {
            temp += 0x28;
        }

        // Extract lower 6 bits
        int binary6bit = temp & 0x3F;

        // Return 6-bit binary string
        return String.format("%6s", Integer.toBinaryString(binary6bit)).replace(' ', '0');
    }

    public static String stringTo168bit(String inputString) throws IllegalArgumentException {

        // Convert each character to 6-bit binary
        StringBuilder combinedBits = new StringBuilder();
        for (char c : inputString.toCharArray()) {
            int asciiCode = (int) c;
            String bit6 = asciiTo6bit(asciiCode);
            combinedBits.append(bit6);
        }

        return combinedBits.toString();
    }

    public static Map<String, Map<String, Object>> parseAisMessage(String binaryMessage) throws IllegalArgumentException {

        Map<String, Map<String, Object>> fields = new HashMap<>();

        // 1. Message ID
        Map<String, Object> messageId = new HashMap<>();
        messageId.put("binary", binaryMessage.substring(0, 6));
        messageId.put("value", Integer.parseInt(binaryMessage.substring(0, 6), 2));
        messageId.put("description", "Message type identifier");
        fields.put("message_id", messageId);

        // 2. Repeat Indicator
        Map<String, Object> repeatIndicator = new HashMap<>();
        repeatIndicator.put("binary", binaryMessage.substring(6, 8));
        repeatIndicator.put("value", Integer.parseInt(binaryMessage.substring(6, 8), 2));
        repeatIndicator.put("description", "Controls message retransmission");
        fields.put("repeat_indicator", repeatIndicator);

        // 3. User ID/MMSI
        Map<String, Object> userId = new HashMap<>();
        userId.put("binary", binaryMessage.substring(8, 38));
        userId.put("value", Integer.parseInt(binaryMessage.substring(8, 38), 2));
        userId.put("description", "MMSI number (ship unique identifier)");
        fields.put("user_id", userId);

        // 4. UTC 年
        Map<String, Object> utcYear = new HashMap<>();
        utcYear.put("binary", binaryMessage.substring(38, 52));
        utcYear.put("value", Integer.parseInt(binaryMessage.substring(38, 52), 2));
        utcYear.put("description", "utcYear");
        fields.put("utcYear", utcYear);

        // 5. UTC 月
        Map<String, Object> utcMonth = new HashMap<>();
        utcMonth.put("binary", binaryMessage.substring(52, 56));
        utcMonth.put("value", Integer.parseInt(binaryMessage.substring(52, 56), 2));
        utcMonth.put("description", "utcMonth");
        fields.put("utcMonth", utcMonth);

        // 6. UTC 日
        Map<String, Object> utcDay = new HashMap<>();
        utcDay.put("binary", binaryMessage.substring(56, 61));
        utcDay.put("value", Integer.parseInt(binaryMessage.substring(56, 61), 2));
        utcDay.put("description", "utcDay");
        fields.put("utcDay", utcDay);

        // 6. UTC 时
        Map<String, Object> utcHour = new HashMap<>();
        utcHour.put("binary", binaryMessage.substring(61, 66));
        utcHour.put("value", Integer.parseInt(binaryMessage.substring(61, 66), 2));
        utcHour.put("description", "utcHour");
        fields.put("utcHour", utcHour);

        // 7. UTC 分
        Map<String, Object> utcMin = new HashMap<>();
        utcMin.put("binary", binaryMessage.substring(66, 72));
        utcMin.put("value", Integer.parseInt(binaryMessage.substring(66, 72), 2));
        utcMin.put("description", "utcMin");
        fields.put("utcMin", utcMin);

        // 8. UTC 秒
        Map<String, Object> utcSec = new HashMap<>();
        utcSec.put("binary", binaryMessage.substring(72, 78));
        utcSec.put("value", Integer.parseInt(binaryMessage.substring(72, 78), 2));
        utcSec.put("description", "utcSec");
        fields.put("utcSec", utcSec);

        // 9. 位置准确度
        Map<String, Object> locationAccuracy = new HashMap<>();
        locationAccuracy.put("binary", binaryMessage.substring(78, 79));
        locationAccuracy.put("value", Integer.parseInt(binaryMessage.substring(78, 79), 2));
        locationAccuracy.put("description", "locationAccuracy");
        fields.put("locationAccuracy", locationAccuracy);

        // 10. 经度 Longitude
        String lonBits = binaryMessage.substring(79, 107);
        int lonValue = Integer.parseInt(lonBits, 2);
        if (lonValue >= (1 << 27)) {
            lonValue = lonValue - (1 << 28);
        }
        double longitude = lonValue / 600000.0;
        Map<String, Object> longitudeField = new HashMap<>();
        longitudeField.put("binary", lonBits);
        longitudeField.put("value", lonValue);
        longitudeField.put("description", "Ship longitude coordinate: " + longitude + "° " + (longitude >= 0 ? "East" : "West"));
        fields.put("longitude", longitudeField);

        // 11. 纬度 Latitude
        String latBits = binaryMessage.substring(107, 134);
        int latValue = Integer.parseInt(latBits, 2);
        if (latValue >= (1 << 26)) {
            latValue = latValue - (1 << 27);
        }
        double latitude = latValue / 600000.0;
        Map<String, Object> latitudeField = new HashMap<>();
        latitudeField.put("binary", latBits);
        latitudeField.put("value", latValue);
        latitudeField.put("description", "Ship latitude coordinate: " + latitude + "° " + (latitude >= 0 ? "North" : "South"));
        fields.put("latitude", latitudeField);

        // 12. 电子定位装置的类型
        Map<String, Object> deviceLocateType = new HashMap<>();
        deviceLocateType.put("binary", binaryMessage.substring(134, 138));
        deviceLocateType.put("value", Integer.parseInt(binaryMessage.substring(134, 138), 2));
        deviceLocateType.put("description", "deviceLocateType");
        fields.put("deviceLocateType", deviceLocateType);

        // 13. 远距离广播消息的传输控制
        Map<String, Object> translateControl = new HashMap<>();
        translateControl.put("binary", binaryMessage.substring(138, 139));
        translateControl.put("value", Integer.parseInt(binaryMessage.substring(138, 139), 2));
        translateControl.put("description", "translateControl");
        fields.put("translateControl", translateControl);

        // 14. 备用
        Map<String, Object> reserve = new HashMap<>();
        reserve.put("binary", binaryMessage.substring(139, 148));
        reserve.put("value", Integer.parseInt(binaryMessage.substring(139, 148), 2));
        reserve.put("description", "reserve");
        fields.put("reserve", reserve);

        // 15. RAIM 标志
        Map<String, Object> raim = new HashMap<>();
        raim.put("binary", binaryMessage.substring(148, 149));
        raim.put("value", Integer.parseInt(binaryMessage.substring(148, 149), 2));
        raim.put("description", "raim");
        fields.put("raim", raim);

        // 16. 通信状态
        Map<String, Object> comamuState = new HashMap<>();
        comamuState.put("binary", binaryMessage.substring(149, 168));
        comamuState.put("value", Integer.parseInt(binaryMessage.substring(149, 168), 2));
        comamuState.put("description", "comamuState");
        fields.put("comamuState", comamuState);

        return fields;
    }

    public static void printAisFields(Map<String, Map<String, Object>> fields) {
        System.out.println("AIS Message Parsing Results:");
        for (Map.Entry<String, Map<String, Object>> entry : fields.entrySet()) {
            String fieldName = entry.getKey();
            Map<String, Object> data = entry.getValue();

            // Convert snake_case to Title Case
            String[] words = fieldName.split("_");
            StringBuilder titleCase = new StringBuilder();
            for (String word : words) {
                titleCase.append(Character.toUpperCase(word.charAt(0)))
                        .append(word.substring(1))
                        .append(" ");
            }

            System.out.println("\n" + titleCase.toString().trim() + ":");
            System.out.println("  Binary: " + data.get("binary"));
            System.out.println("  Value: " + data.get("value"));
            System.out.println("  Description: " + data.get("description"));
        }
    }

    public static void main(String[] args) {
        String testString = "403t>=1vUpRDH`bgt@Apig700H>W";

        try {
            // Convert string to 168-bit binary
            String binaryMessage = stringTo168bit(testString);
            System.out.println("Input string: " + testString);
            System.out.println("Converted 168-bit binary: " + binaryMessage);
            System.out.println("Binary length: " + binaryMessage.length());

            // Parse AIS message
            Map<String, Map<String, Object>> aisFields = parseAisMessage(binaryMessage);

            // Print parsing results
            printAisFields(aisFields);

        } catch (IllegalArgumentException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }


    public static String binaryStringToOriginal(String binaryStr) throws IllegalArgumentException {
        try{
            // 检查输入是否为有效的二进制字符串且长度是6的倍数
            if (binaryStr == null || binaryStr.isEmpty() || !binaryStr.matches("[01]+")) {
                throw new IllegalArgumentException("Input must be a non-empty binary string");
            }
            if (binaryStr.length() % 6 != 0) {
                throw new IllegalArgumentException("Binary string length must be a multiple of 6");
            }

            StringBuilder result = new StringBuilder();
            int length = binaryStr.length();

            // 每6位一组处理
            for (int i = 0; i < length; i += 6) {
                String bit6 = binaryStr.substring(i, Math.min(i + 6, length));
                char c = sixBitToAscii(bit6);
                result.append(c);
            }
            return result.toString();
        }catch (Exception e){
            e.printStackTrace();
        }
        return "-1";


    }

    public static char bit6ToAscii(String bit6) throws IllegalArgumentException {
        // 检查是否为6位二进制字符串
        if (bit6.length() != 6 || !bit6.matches("[01]{6}")) {
            throw new IllegalArgumentException("Input must be a 6-bit binary string");
        }

        // 将二进制字符串转换为整数
        int binary6bit = Integer.parseInt(bit6, 2);

        // 反向计算原始ASCII码
        int temp = binary6bit;

        // 反向处理原始转换逻辑
        if (temp > 0xA0) {
            temp -= 0x20;
        } else {
            temp -= 0x28;
        }

        temp -= 0x28;

        // 范围检查
        if (temp < 0x30 || temp > 0x77) {
            throw new IllegalArgumentException("Decoded ASCII code " + temp + " out of range");
        }
        if (temp >= 0x58 && temp <= 0x59) {
            throw new IllegalArgumentException("Decoded ASCII code " + temp + " in reserved range");
        }

        return (char) temp;
    }


}